package cae.logic.chat;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

import org.apache.log4j.Logger;

import cae.logic.CaeMessage;
import cae.logic.destination.CaeDestination;
import cae.logic.destination.CaeDestinatiosManager;
import cae.logic.history.CaeMessageHistory;
import cae.logic.util.CaeClipConfiguration;

public class CaeChatManager extends Observable implements Runnable
{
	private ServerSocket socket;
	private boolean stop = false;
	private static Logger logger = Logger.getLogger(CaeChatManager.class);
	private List<CaeChatMessage> lastMessages;
	
	public CaeChatManager()
	{
		try
		{
			this.socket = new ServerSocket(CaeClipConfiguration.getInstance().getIProp(CaeClipConfiguration.PORT_CHAT));
			this.lastMessages = new ArrayList<CaeChatMessage>();
		}
		catch(IOException e)
		{
			logger.error("No se pudo iniciar el chat", e);
			throw new RuntimeException("No se pudo iniciar el chat", e);
		}
	}
	
	public void run()
	{
		while(!stop)
		{
			Socket csocket;
			try {
				csocket = socket.accept();
				new Thread(new CaeChatSingleMessageProcesor(csocket)).start();
			} catch (IOException e) {
				logger.info("Falla al recibir mensaje, es posible que no sea un error:", e);
			}
			

		}
	}
	
	private class CaeChatSingleMessageProcesor implements Runnable
	{
		Socket csocket;
		
		private CaeChatSingleMessageProcesor(Socket csocket)
		{
			this.csocket = csocket;
		}
		
		public void run()
		{
			try 
			{
				ObjectInputStream ois = new ObjectInputStream(csocket.getInputStream());
				CaeChatMessageStub stub = (CaeChatMessageStub) ois.readObject();
				String messageText = stub.getText();
				
				String from = csocket.getInetAddress().getHostName();
	
				CaeMessage message = new CaeMessage(messageText, from);
				
				CaeMessageHistory.getInstance().addMessage(message);

				CaeChatMessage m = new CaeChatMessage(messageText, from);
				
				lastMessages.add(m);
				setChanged();
				notifyObservers(m);
			} 
			catch (Exception e)
			{
				logger.info("Falla al recibir mensaje, es posible que no sea un error:", e);
				// error al recibir mensaje IGNORAR;
				// POR EJEMPLO CUANDO TESTEA CONECCION
			}
		}
	}
	
	public static void sendMessage(String message, CaeDestination destination) throws IOException
	{
		Socket s = new Socket();
		s.connect(new InetSocketAddress(destination.getMachine()[0], destination.getChatPort()));
		
		CaeChatMessageStub stub = new CaeChatMessageStub(message);
		ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
		oos.writeObject(stub);
		
		oos.close();
		
		s.close();
	}
	
	public static void sendMessage(final String message)
	{
		List<CaeDestination> dests = CaeDestinatiosManager.getInstance().getDestinations();
		
		for (final CaeDestination destination : dests)
		{
			new Thread(new Runnable()
			{
				public void run() {
					try {
						sendMessage(message, destination);
					} catch (IOException e) {
						// ESPERADO, GENTE NO CONECTADA
						logger.debug(e, e);
					}
				}
			}).start();
		}
	}
	
	public List<CaeChatMessage> getLastMessages()
	{
		return lastMessages;
	}
	

}
